package com.kafka.utils;

import org.apache.commons.codec.binary.Base64;

/**
 * Code Format Conversion Class
 *
 * @version 1.0 2018.04
 */
public class CodeConvertor {

    private static final char[] EBCDIC_CODE = {
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ' ', 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, '.', '<', '(', '+', '|', '&', 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '!', '$', '*', ')', ';', 0x00, '-', '/',
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ',', '%', '_', '>', '?',
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ':', '#', '@', '\'',
            '=', '"', 0x00, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 's', 't', 'u', 'v', 'w', 'x',
            'y', 'z', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'A', 'B', 'C',
            'D', 'E', 'F', 'G', 'H', 'I', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'J', 'K',
            'L', 'M', 'N', 'O', 'P', 'Q', 'R', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, '0',
            '1', '2', '3', '4', '5', '6', '7', '8', '9', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };

    /**
     * asc byte[] 转 16进制 byte[]
     *
     * @param asc byte[]
     * @return byte[]
     */
    public static byte[] ascToHex(byte[] asc) throws Exception {
        if (asc == null)
            return null;

        StringBuffer hex = new StringBuffer();
        for (int i = 0; i < asc.length; i++) {
            String hv = Integer.toHexString(asc[i] & 0xFF);
            if (hv.length() < 2) {
                hex.append(0);
            }
            hex.append(hv);
        }
        byte[] result = hex.toString().getBytes(Charset.UTF_8);
        return result;
    }

    /**
     * asc String 转 16进制 String
     *
     * @param asc String
     * @return String
     */
    public static String ascToHex(String asc) throws Exception {
        if (asc == null)
            return null;

        StringBuffer hex = new StringBuffer();
        byte[] temp = asc.getBytes(Charset.UTF_8);
        for (int i = 0; i < temp.length; i++) {
            String hv = Integer.toHexString(temp[i] & 0xFF);
            if (hv.length() < 2) {
                hex.append(0);
            }
            hex.append(hv);
        }

        return hex.toString();
    }

    /**
     * byte[] 转 asc byte[]
     *
     * @param hex
     * @return
     */
    public static byte[] hexToAsc(byte[] hex) throws Exception {
        if (hex == null) {
            return null;
        }

        byte[] asc = new byte[hex.length / 2];
        for (int i = 0, j = 0; i < hex.length - 1; i += 2, j++) {
            asc[j] = (byte) Integer.parseInt(new String(hex, Charset.UTF_8).substring(i, (i + 2)), 16);
        }
        return asc;
    }

    /**
     * 16进制String转asc String
     *
     * @param hex String
     * @return String
     */
    public static String hexToAsc(String hex) throws Exception {
        if (hex == null)
            return null;
        String result = null;
        byte[] temp = hex.getBytes(Charset.UTF_8);
        byte[] asc = new byte[temp.length / 2];
        for (int i = 0, j = 0; i < temp.length - 1; i += 2, j++) {
            asc[j] = (byte) Integer.parseInt(hex.substring(i, (i + 2)), 16);
        }
        result = new String(asc, Charset.UTF_8);
        return result;
    }

    private static byte asc_to_bcd(byte asc) {
        byte bcd;

        if ((asc >= '0') && (asc <= '9')) {
            bcd = (byte) (asc - '0');
        } else if ((asc >= 'A') && (asc <= 'F')) {
            bcd = (byte) (asc - 'A' + 10);
        } else if ((asc >= 'a') && (asc <= 'f')) {
            bcd = (byte) (asc - 'a' + 10);
        } else {
            bcd = (byte) (asc - 48);
        }
        return bcd;
    }

    /**
     * asc byte[] 转bcd byte[]
     *
     * @param asc byte[]
     * @return byte[]
     */
    public static byte[] ascToBcd(byte[] asc) {
        if (asc == null) {
            return null;
        }

        byte[] bcd = new byte[asc.length / 2];
        int j = 0;
        for (int i = 0; i < (asc.length + 1) / 2; i++) {
            bcd[i] = asc_to_bcd((byte) asc[j++]);
            bcd[i] = (byte) (((j >= asc.length) ? 0x00 : asc_to_bcd((byte) asc[j++]))
                    + (bcd[i] << 4));
        }

        return bcd;
    }

    /**
     * asc String 转 bcd String
     *
     * @param asc String
     * @return String
     */
    public static String ascToBcd(String asc) throws Exception {
        if (asc == null) {
            return null;
        }
        String result = null;
        byte[] temp = asc.getBytes(Charset.UTF_8);
        byte[] bcd = new byte[temp.length / 2];
        int j = 0;
        for (int i = 0; i < (temp.length + 1) / 2; i++) {
            bcd[i] = asc_to_bcd((byte) temp[j++]);
            bcd[i] = (byte) (((j >= temp.length) ? 0x00
                    : asc_to_bcd((byte) temp[j++])) + (bcd[i] << 4));
        }
        result = new String(bcd, Charset.UTF_8);
        return result;
    }

    /**
     * bcd byte[] 转 asc byte[]
     *
     * @param bcd byte[]
     * @return byte[]
     */
    public static byte[] bcdToAsc(byte[] bcd) {
        if (bcd == null) {
            return null;
        }

        byte[] asc = new byte[bcd.length * 2];
        byte val;

        for (int i = 0; i < bcd.length; i++) {
            val = (byte) (((bcd[i] & 0xf0) >> 4) & 0x0f);
            asc[i * 2] = (byte) (val > 9 ? val + 'A' - 10 : val + '0');

            val = (byte) (bcd[i] & 0x0f);
            asc[i * 2 + 1] = (byte) (val > 9 ? val + 'A' - 10 : val + '0');
        }

        return asc;
    }

    /**
     * bcd String 转 asc String
     *
     * @param bcd String
     * @return String
     */
    public static String bcdToAsc(String bcd) throws Exception {
        if (bcd == null) {
            return null;
        }
        String result = null;
        byte[] temp = bcd.getBytes(Charset.UTF_8);
        byte[] asc = new byte[temp.length * 2];
        byte val;

        for (int i = 0; i < temp.length; i++) {
            val = (byte) (((temp[i] & 0xf0) >> 4) & 0x0f);
            asc[i * 2] = (byte) (val > 9 ? val + 'A' - 10 : val + '0');

            val = (byte) (temp[i] & 0x0f);
            asc[i * 2 + 1] = (byte) (val > 9 ? val + 'A' - 10 : val + '0');
        }
        result = new String(asc, Charset.UTF_8);
        return result;
    }

    /**
     * asc byte[] 转 Ebcd char[]
     *
     * @param asc byte[]
     * @return char[]
     */
    public static char[] ascToEbcd(byte[] asc) {
        if (asc == null) {
            return null;
        }

        char[] ebcd = new char[asc.length];

        for (int i = 0; i < asc.length; i++) {
            for (int j = 0; j < CodeConvertor.EBCDIC_CODE.length; j++) {
                if (asc[i] == CodeConvertor.EBCDIC_CODE[j]) {
                    ebcd[i] = (char) j;
                    break;
                }
            }
        }

        return ebcd;
    }

    /**
     * asc String 转 Ebcd String
     *
     * @param asc String
     * @return String
     */
    public static String ascToEbcd(String asc) throws Exception {
        if (asc == null) {
            return null;
        }

        byte[] temp = asc.getBytes(Charset.UTF_8);
        String result = "";
        if (temp != null) {
            char[] ebcd = new char[temp.length];
            for (int i = 0; i < temp.length; i++) {
                for (int j = 0; j < CodeConvertor.EBCDIC_CODE.length; j++) {
                    if (temp[i] == CodeConvertor.EBCDIC_CODE[j]) {
                        ebcd[i] = (char) j;
                        break;
                    }
                }
            }
            result = new String(ebcd);
        }

        return result;
    }

    /**
     * ebcd byte[] 转asc byte[]
     *
     * @param ebcd byte[]
     * @return byte[]
     */
    public static byte[] ebcdToAsc(char[] ebcd) {
        if (ebcd == null) {
            return null;
        }

        byte[] asc = new byte[ebcd.length];

        for (int i = 0; i < ebcd.length; i++) {
            asc[i] = (byte) CodeConvertor.EBCDIC_CODE[ebcd[i]];
        }

        return asc;
    }

    /**
     * ebcd String 转 asc String
     *
     * @param ebcd String
     * @return String
     */
    public static String ebcdToAsc(String ebcd) throws Exception {
        if (ebcd == null) {
            return null;
        }

        char[] temp = ebcd.toCharArray();

        byte[] asc = new byte[temp.length];

        for (int i = 0; i < temp.length; i++) {
            asc[i] = (byte) CodeConvertor.EBCDIC_CODE[temp[i]];
        }
        String result = new String(asc, Charset.UTF_8);

        return result;
    }

    /**
     * Base64编码
     *
     * @param binaryData byte[]
     * @return byte[]
     */
    public static byte[] encodeBase64(byte[] binaryData) {
        if (binaryData == null) {
            return null;
        }

        return Base64.encodeBase64(binaryData);
    }

    /**
     * Base64编码
     *
     * @param binaryData String
     * @return String
     */
    public static String encodeBase64(String binaryData) throws Exception {
        if (binaryData == null) {
            return null;
        }
        String result = new String(Base64.encodeBase64(binaryData.getBytes(Charset.UTF_8)));
        return result;
    }

    /**
     * Base64解码
     *
     * @param base64Date byte[]
     * @return byte[]
     */
    public static byte[] decodeBase64(byte[] base64Date) {
        if (base64Date == null) {
            return null;
        }

        return Base64.decodeBase64(base64Date);
    }

    /**
     * Base64解码
     *
     * @param base64Date String
     * @return String
     */
    public static String decodeBase64(String base64Date) throws Exception {
        if (base64Date == null) {
            return null;
        }
        String result = new String(Base64.decodeBase64(base64Date.getBytes(Charset.UTF_8)), Charset.UTF_8);
        return result;
    }

    /**
     * gbk String 转utf8 String
     *
     * @param gbkStr String
     * @return String
     * @throws
     */
    public static String gbkToUtf8(String gbkStr) throws Exception {
        if (gbkStr == null) {
            return null;
        }
        byte[] utfData;

        utfData = gbkStr
                .getBytes(Charset.UTF_8);
        return new String(utfData, Charset.UTF_8);

    }

    /**
     * utf8 String转gbk String
     *
     * @param utf8Str String
     * @return String
     * @throws
     */
    public static String utf8ToGbk(String utf8Str) throws Exception {
        if (utf8Str == null) {
            return null;
        }
        byte[] gbkData;
        gbkData = utf8Str.getBytes(Charset.GBK);
        return new String(gbkData, Charset.GBK);
    }

    /**
     * gbk byte[] 转 utf8 byte[]
     *
     * @param gbkData byte[]
     * @return byte[]
     * @throws
     */
    public static byte[] gbkToUtf8(byte[] gbkData) throws Exception {
        if (gbkData == null) {
            return null;
        }
        return new String(gbkData, Charset.GBK)
                .getBytes(Charset.UTF_8);

    }

    /**
     * utf8 byte[]转gbk byte[]
     *
     * @param utf8Data byte[]
     * @return byte[]
     * @throws
     */
    public static byte[] utf8ToGbk(byte[] utf8Data) throws Exception {
        if (utf8Data == null) {
            return null;
        }
        return new String(utf8Data, Charset.UTF_8)
                .getBytes(Charset.GBK);
    }
}
